import time
import serial

def reverse_byte(inp, sort):
    if sort == 'c':
        byte = '1'
    else:
        byte = '0'
    byte += inp
    inp = inp[-1::-1]
    if byte.count('0') % 2 == 0:
        if inp[-1] == '1':
            return serial.PARITY_ODD, inp
        else:
            return serial.PARITY_EVEN, inp
    if byte.count('0') % 2 == 1:
        if inp[-1] == '1':
            return serial.PARITY_EVEN, inp
        else:
            return serial.PARITY_ODD, inp

def make_byte(inp, sort):
    if sort == 'c':
        byte = '1' + inp
    else:
        byte = '0' + inp
    if byte.count('0') % 2 == 0:
        return serial.PARITY_ODD, inp
    else:
        return serial.PARITY_EVEN, inp

def bin(num):
    num = oct(num)
    oct_table = ['000', '001', '010', '011', '100', '101', '110', '111']
    if len(num) == 4:
        return oct_table[int(num[-3])] + oct_table[int(num[-2])] + oct_table[int(num[-1])]
    elif len(num) == 3:
        return "00" + oct_table[int(num[-2])] + oct_table[int(num[-1])]
    else:
        return "00000" + oct_table[int(num[-1])]

def start(port):
    startup = ["c00000000", "d11001110", "c00000001", "d10100000", "c00000010",
               "d10110010", "c00000011", "d10000000", "c00000100", "d01000000",
               "c00000101", "d10000000", "c00000110", "d00001000"]
    for inst in startup:
        parity, byte = make_byte(inst[1:], inst[0])
        port.parity = parity
        port.write(chr(int(byte, 2)))
        print ord(port.read(1))
        time.sleep(0.002)

def spam(port):
    parity, byte = make_byte("10100000", "1")
    port.write(chr(int(byte, 2)))
    print ord(port.read(1))
    time.sleep(0.002)
    end_time = time.time() + 5
    parity, byte = make_byte("01001110", "0")
    port.parity = parity
    while time.time() < end_time:
        port.write(chr(int(byte, 2)))
        print ord(port.read(1))
        time.sleep(0.002)
    print "sent data"
    time.sleep(3)
    parity, byte = make_byte("00100000", "1")
    port.write(chr(int(byte, 2)))
    try:
        print ord(port.read(1))
    except TypeError:
            print "no data!"
    time.sleep(0.002)

if __name__ == "__main__":
    port = serial.Serial(0, 9600, timeout=1)
    print port
    port.open()
    while True:
        inp = raw_input("Enter 8 binary bits followed by\n'c' or 'd' for control or data or 'x' to quit: ")
        if inp == "x":
            break
        elif inp == "s":
            start(port)
            continue
        elif inp == "test":
            spam(port)
            continue
        elif inp == "recv":
            port.parity = "O"
            print port
            while True:
                #print hex(ord(port.read(1)))
                print bin(ord(port.read(1)))
        else:
            parity, byte = make_byte(inp[:8], inp[8])
        port.parity = parity
        #print port
        #print byte
        print "sent", byte
        port.write(chr(int(byte, 2)))
        try:
            data = port.read(2)
            print data
            print "recv", bin(ord(data[0])), bin(ord(data[1]))
        except IndexError:
            print "no data!"
        time.sleep(1)
        port.flushInput()
